﻿#ifndef __AVOID_BW_CONTROL_CTLDEFINE_HEAD_FILE_INCLUDED__
#define __AVOID_BW_CONTROL_CTLDEFINE_HEAD_FILE_INCLUDED__
#include "ctlColorDefine.h"
#include <string>

namespace swui
{
	//ControlType
	enum class ctlControlType : unsigned
	{
			ctlUndefined,
			ctlStatic,
			ctlButton, 
			ctlCheckBox, 
			ctlRadioBox, 
			ctlEdit, 
			ctlScroll,
			ctlProgress,
			ctlSingleEdit,
			ctlPassword,
			ctlSingleLabel,
			ctlList, 
			ctlComboBox,
			ctlImageButton,
			ctlSlider,
			ctlTree
	};
	//Position
	template<typename Type>
	struct ctlPointTemplate
	{
		Type x, y;
		ctlPointTemplate() : x(0), y(0) {}
		ctlPointTemplate(Type x, Type y)
		{
			this->x = x, this->y = y;
		}
	};
	template<typename Type>
	struct ctlRectTemplate
	{
		Type x, y, cx, cy;
		ctlRectTemplate() : x(0), y(0), cx(0), cy(0) {}
		ctlRectTemplate(Type x, Type y, Type cx, Type cy)
		{
			this->x = x, this->y = y;
			this->cx = cx, this->cy = cy;
		}
		ctlRectTemplate(ctlPointTemplate<Type> point, Type cx, Type cy)
		{
			x = point.x, y = point.y;
			this->cx = cx, this->cy = cy;
		}
		ctlRectTemplate& merge(const ctlRectTemplate* rhs)
		{
			if(x < rhs->x) cx -= rhs->x - x, x = rhs->x;
			if(y < rhs->y) cy -= rhs->y - y, y = rhs->y;
			if(y + cy > rhs->y + rhs->cy) cy = rhs->cy;
			if(x + cx > rhs->x + rhs->cx) cx = rhs->cx;
			return *this;
		}
		ctlRectTemplate& deflate(ctlPointTemplate<Type> point)
		{
			x += point.x, y += point.y;
			cx -= point.x * 2, cy -= point.y * 2;
			return *this;
		}
		ctlRectTemplate& inflate(ctlPointTemplate<Type> point)
		{
			x -= point.x, y -= point.y;
			cx += point.x * 2, cy += point.y * 2;
			return *this;
		}
		ctlRectTemplate& merge(ctlRectTemplate rhs) 
		{
			return merge(&rhs);
		}
		ctlRectTemplate& offset(ctlPointTemplate<Type> point)
		{
			x += point.x, y += point.y;
			return *this;
		}
		ctlRectTemplate& deflate(Type x, Type y)
		{
			return deflate(ctlPointTemplate<Type>(x, y));
		}
		ctlRectTemplate& inflate(Type x, Type y)
		{
			return inflate(ctlPointTemplate<Type>(x, y));
		}
		ctlRectTemplate& offset(Type x, Type y)
		{
			return offset(ctlPointTemplate<Type>(x, y));
		}
		Type getLeft() { return x; }
		Type getTop() { return y; }
		Type getBottom() { return y + cy; }
		Type getRight() { return x + cx; }
		Type getWidth() { return cx; }
		Type getHeight() { return cy; }
	};
	typedef ctlPointTemplate<int> ctlPoint;
	typedef ctlRectTemplate<int> ctlRect;
	//MouseEvent
	enum class ctlMouseEventType : unsigned
	{
		leftDown, leftUp, leftPress, leftDBClick,
		rightDown, rightUp, rightPress, rightDBClick,
		enter, leave, move, wheel
	};
	enum class ctlMouseEventModel : unsigned
	{
		/* 鼠标事件模型（对 enter 和 leave 无效）
		 * 如果是 cut 模型，那么当最下级控件收到事件后，
		 * 不会再向上发送给其它控件
		 * 如果是 bubble 模型，那么当最下级控件处理事件后，
		 * 会发送鼠标事件给它的父控件
		 * 如果是 capture 模型，那么当最下级控件处理事件前，
		 * 会发送鼠标事件给其父控件 
		 * 另外，事件模型对于焦点没有影响 */
		cut, bubble, capture
	};
	class ctlRoot;
	struct ctlMouseEvent
	{
		typedef const void* paramType;
		ctlPoint mousePos;		//相对于当前控件的坐标
		ctlPoint absolutePos;	//相对于当前窗口的坐标
		ctlMouseEventType eventType;			//事件类型
		ctlMouseEventModel eventModel;	//事件模型
		int wheelDelta;					//鼠标滚动的相对量（1 为单位，正向上，负向下）
		ctlRoot* eventFrom;			/*对于 cut 类型的事件，那么这个值为其父控件
												 *对于 bubble 和 capture，这个值为其子控件 */
		paramType userParam;		//用户数据
		bool* nextHandler;			//决定是否向下一个处理程序发送事件
	};
	//KeyEvent
	enum class ctlKeyEventType : unsigned {
		down, up, input
	};
	struct ctlKeyEvent
	{
		typedef const void* paramType;
		ctlKeyEventType eventType;	//事件类型
		union {
			//当 eventType 是 input 时，text 或 wtext 有意义
			char text[3];		//对于中文字符等 不会有两次 input 事件，但 text[1] 会被非零值填充
									//对于英文 text[0] 是字符，text[1] 和 text[2] 是零
			std::wstring::value_type wtext;
			//当 eventType 是 down 和 up 时，virtualKey 有意义
			int virtualKey;	//(VK_...) 详见MSDN
		} charInfo;
		paramType userParam;		//用户数据
		bool* nextHandler;		//决定是否向下一个处理程序发送事件
	};
	//PositionEvent
	enum class ctlPositionEventType : unsigned {
		size, move,
		sizeing, moving
	};
	struct ctlPositionEvent
	{
		typedef const void* paramType;
		ctlPositionEventType eventType;	//事件类型
		/* 对于 size 事件，这个保存的是控件的宽度（x）和高度（y）
			对于 move 事件，这个保存的是控件的左上角坐标 
			对于 *ing 事件，这个保存的是事件结束后改变的信息 */
		ctlPoint position;
		bool* isAllow;	//决定是否允许位置变换（仅 sizing 和 moving 有效）
		bool* nextHandler;		//决定是否向下一个处理程序发送事件
		paramType userParam;		//用户数据
	};
	/* 如果没有详细注明 info 的类型
	 * 那么 info 的类型就是 ctlNotify + 枚举名称
	 */
	enum class ctlNotifyEventType : unsigned
	{
		/* ctlCheckBox, ctlRadioBox 选中标志改变时通告（info 无用）
		 * ctlList 的选中行（单元格）改变时会发送
		 * ctlComboBox 选中改变时也会发送 */
		selectChange,
		// 获取或丧失焦点（info 无用）
		focus, blur,
		/* IDrag 接口使用
		 * 当控件的拖动开始、结束或正在拖时通告
		 */ drag, 
		/* IUserDraw 接口使用
		 * 当重绘时通告
		 * info 为 ctlNotifyUserDraw
		 */ draw,
		 // 文本框控件的通告
		edit, editChange,
		// 滚动条、滑动条、进度条的通告
		scroll,
		// 列表的通告
		list, listEdit,
		/* 鼠标点击测试
		 * 这个通知或者默认测试函数返回 true 则表示点在控件上 */
		hittest
	};
	struct ctlNotifyEvent
	{
		typedef const void* paramType;
		ctlNotifyEventType eventType;
		void* info;
		bool* nextHandler;
		paramType userParam;
	};
	struct ctlNotifyScroll
	{
		//将要滚动到的逻辑距离
		unsigned logicLength;
		//滚动完后的百分比
		float percent;
		//是否允许滚动
		bool *isAllow;
	};
	struct ctlNotifyEdit
	{
		//如果是通过 paste 插入字符，那么不会触发 insert
		enum { copy, paste, cut, insert } state;
		bool* isAllow;		//是否允许执行通告
		std::wstring* str;	//可以更改 str 的内容
		//如果是 insert 事件那么以下有效，上面的无效
		union {
			std::wstring::value_type wc;
			char c[3];
		} text;
	};
	struct ctlNotifyHittest
	{
		bool* isInControl;
		ctlPoint mousePos;
		ctlPoint absolutePos;
	};
	enum class ctlAccess : unsigned 
	{
		read = 1, write = 2,
		readWrite = read | write,
		writeRead = readWrite,
		none = 0
	};
	enum class ctlDirection : unsigned {
		x = 1, y = 2, 
		xy = x | y, none = 0
	};
	enum class ctlScrollDirection : unsigned {
		vertical, horizontal
	};
	enum class ctlOverflowScroll : unsigned {
		hide, show, automatic
	};
}

#endif